using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections;
using AgreementConstants = PHSRAG.Insight21.Agreements.AgreementConstants;
using AgreementsConstants = PHSRAG.Insight21.InsightUtilities.Constants.AgreementsConstants;
using ExpenseConstants = PHSRAG.Insight21.Agreements.AgreementConstants.ExpenseInfoConstants;

namespace PHSRAG.Insight21.Agreements
{
	/// <summary>
	/// Contains the header, linkbutton and footer templates,
	/// needed for the header ,item and footer templates of template columns
	/// being added dynamically to the expense info data grid.
	/// </summary>
	public class ExpenseTemplates
	{
		#region Constants
		private const string LinkStyle = "categoryLink";
	    private const string NegativeLinkStyle = "negativeCategoryLink";
		private const string NegativeCurrencyStyle = "DataGridNegativeCurrencyItem";
		#endregion

		#region Header Template

		/// <summary>
		/// Header Template class, contains controls and methods needed for the
		/// display of header information in the template columns of the expense info grid.
		/// </summary>
		public class HeaderTemplate: ITemplate
		{
			#region Constants
			private const string HeaderTableStyle = "HeaderTable";
			#endregion
			
			#region Member Variables
			// Is used to conditionally create fund label in the header
			private bool createFundLabel;
			// The text to be displayed in the header.
			private string headerText;
			// The number of funds per column to be displayed on the header 
			// if fund label is created
			private string fundsPerMonthText;
			#endregion

			#region Constructor
			/// <summary>
			/// Constructs the header template and intializes the private variables of this
			/// class with the specifed values.
			/// </summary>
			/// <param name="isDetails">indicates if fund label has to be created</param>
			/// <param name="expenseMonth">the header text to be displyed</param>
			/// <param name="noofFundsInExpenseMonth">No of fund per expense month to be displyed(if not details)</param>
			public HeaderTemplate(bool isDetails, string expenseMonth, string noofFundsInExpenseMonth)
			{
				createFundLabel = !isDetails;
				headerText = expenseMonth;
				fundsPerMonthText = noofFundsInExpenseMonth;
			}
			#endregion			
			
			#region Public Properties
			public string HeaderText
			{
				get { return headerText; }
			}
			#endregion
			
			#region ITemplate Members		

			/// <summary>
			/// Defines the Control object to which the child controls are added.
			/// </summary>
			/// <param name="container">The Control object to contain the instantiated controls.</param>
			public void InstantiateIn(Control container)
			{
				Table table = new Table();
				table.CssClass = HeaderTableStyle;
				
				TableRow expenseMonthRow = new TableRow();
				table.Rows.Add(expenseMonthRow);
				TableCell expenseMonthCell = new TableCell();
				expenseMonthRow.Cells.Add(expenseMonthCell);
				Label expenseMonth = new Label();
				expenseMonth.Text = headerText;
				expenseMonthCell.Controls.Add(expenseMonth);
				
				if(createFundLabel)
				{
					TableRow fundsPerMonthRow = new TableRow();
					table.Rows.Add(fundsPerMonthRow);
					TableCell fundsPerMonthCell = new TableCell();
					fundsPerMonthRow.Cells.Add(fundsPerMonthCell);
					Label fundsPerMonth = new Label();
					fundsPerMonth.Text = string.Format("Funds: {0}", fundsPerMonthText);
					fundsPerMonthCell.Controls.Add(fundsPerMonth);
				}				
				container.Controls.Add(table);
			}
			#endregion			
		}
		#endregion

		#region Link Button Template
		/// <summary>
		/// Link Button template class. Contains controls and methods needed for the
		/// display of item and alternating item information in the template columns 
		/// of the expense info grid.
		/// </summary>
		public class LinkButtonTemplate: ITemplate
		{
			#region Member Variables
			// The data field from which the data has to be retrieved for display.
			private string dataField;
			private string command;
			#endregion

			#region Constructor
			/// <summary>
			/// Constructs the Link button template and intializes the private variable of this
			/// class with the specifed value.
			/// </summary>
			/// <param name="columnName">the name of column from which data has to pe picked
			/// for the link button template</param>
			public LinkButtonTemplate(string columnName, string commandName)
			{
				dataField = columnName;
				command = commandName;
			}
			#endregion
			
			#region ITemplate Members

			/// <summary>
			/// Defines the Control object to which the child controls are added.
			/// </summary>
			/// <param name="container">The Control object to contain the instantiated controls.</param>
			public void InstantiateIn(Control container)
			{
				LinkButton linkButton = new LinkButton();
				linkButton.CommandName = command;
				linkButton.CssClass = LinkStyle;
				linkButton.DataBinding += new EventHandler(OnLinkButtonDataBinding);				
				container.Controls.Add(linkButton);				
			}

			#endregion

			/// <summary>
			/// Handler for event when the link button binds to a datasource.
			/// Gets the data from the DataRowView of the dataitem of the naming container(DataGridItem),
			/// checks if its negative and accordingly sets the style and text of the link button.
			/// To retrieve the data for the link button, the value stored in the datafield variable
			/// is used.
			/// </summary>
			/// <param name="sender">Control which raised the event</param>
			/// <param name="e">Argument associated with the event</param>
			private void OnLinkButtonDataBinding(object sender, EventArgs e)
			{
				LinkButton linkButton = (LinkButton)sender;
                decimal amount = Convert.ToDecimal(((DataRowView)((DataGridItem)linkButton.NamingContainer).DataItem)[dataField].ToString());       //Decimal.Round(Convert.ToDecimal(((DataRowView)((DataGridItem)linkButton.NamingContainer).DataItem)[dataField].ToString()), 0);
				if(amount < 0)
					linkButton.CssClass = NegativeLinkStyle;
                linkButton.Text = PHSRAG.WebControls.Helper.ProcessDecimals(amount);    //amount.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
			}			
		}
		#endregion

		#region Label Button Template
		/// <summary>
		/// Label template class. Contains controls and methods needed for the
		/// display of item and alternating item information in the template columns 
		/// of the expense info grid.
		/// </summary>
		public class LabelButtonTemplate: ITemplate
		{
			#region Member Variables
			// The data field from which the data has to be retrieved for display.
			private string dataField;
			#endregion

			#region Constructor
			/// <summary>
			/// Constructs the Link button template and intializes the private variable of this
			/// class with the specifed value.
			/// </summary>
			/// <param name="columnName">the name of column from which data has to pe picked
			/// for the link button template</param>
			public LabelButtonTemplate(string columnName)
			{
				dataField = columnName;
			}
			#endregion
			
			#region ITemplate Members

			/// <summary>
			/// Defines the Control object to which the child controls are added.
			/// </summary>
			/// <param name="container">The Control object to contain the instantiated controls.</param>
			public void InstantiateIn(Control container)
			{
				Label label = new Label();
				label.CssClass = LinkStyle;
				label.DataBinding += new EventHandler(OnLabelDataBinding);				
				container.Controls.Add(label);				
			}

			#endregion

			/// <summary>
			/// Handler for event when the link button binds to a datasource.
			/// Gets the data from the DataRowView of the dataitem of the naming container(DataGridItem),
			/// checks if its negative and accordingly sets the style and text of the link button.
			/// To retrieve the data for the link button, the value stored in the datafield variable
			/// is used.
			/// </summary>
			/// <param name="sender">Control which raised the event</param>
			/// <param name="e">Argument associated with the event</param>
			private void OnLabelDataBinding(object sender, EventArgs e)
			{
				Label label = (Label)sender;
				decimal amount = Decimal.Round(Convert.ToDecimal(((DataRowView)((DataGridItem)label.
					NamingContainer).DataItem)[dataField].ToString()), 0);
				if(amount < 0)
					label.CssClass = NegativeCurrencyStyle;
				label.Text = amount.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
			}			
		}
		#endregion

		#region Footer Template
		/// <summary>
		/// FooterTemplate template class. Contains controls and methods needed for the
		/// display of footer information in the template columns of the expense info grid.
		/// </summary>
		public class FooterTemplate: ITemplate
		{
			#region Constants
			private string DefaultAmount = "0";
			private int FirstCellIndex = 0;
			private int NoOfRowsWithLabel = 3;
			private int FirstControlIndex = 0;
			#endregion

			#region Enumerations
			// this needs to be in sync with display order
			// on the screen 
			private enum FooterCategory
			{
				DirectCosts,
				IndirectCosts,
				TotalCosts,
                Revenue,
				CashBalance
			}
			#endregion

			#region Member Variables
			// the cache policy from which the data container for the footer has to be retrieved.
			private Policy.ICachePolicy	cachePolicy;
			// used to determine the column index of the template column. it is
			// used to retrive the corresponding row from the footer tables.
			private int cellIndex;			
			#endregion
			
			#region Constructor
			/// <summary>
			/// Constructs the FooterTemplate and intializes the private variables of this
			/// class with the specifed values.
			/// </summary>
			/// <param name="pageCachePolicy">the cache policy used to store the active dataset</param>
			/// <param name="rowNumber">the current column index of the template column</param>
			public FooterTemplate(Policy.ICachePolicy pageCachePolicy, int rowNumber)
			{
				cachePolicy = pageCachePolicy;
				cellIndex = rowNumber;
			}
			#endregion
			
			#region ITemplate Members			
			
			/// <summary>
			/// Defines the Control object to which the child controls are added.
			/// Four rows are with label and two rows with link buttons are added to the footer.
			/// The labels are for Direct Cost, Direct Cost Balance, Indirect Cost,
			/// Total Cost. Link Buttons are for Revenue and CashBalance.
			/// </summary>
			/// <param name="container">The Control object to contain the instantiated controls.</param>
			public void InstantiateIn(Control container)
			{
				Hashtable h = cachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable;
				
				//Check if the Data for download to excel is present in cache. 
				DataSet dataContainer = (h == null) ? null : (DataSet) h[ExpenseConstants.ActiveDataForDownloadKey];

				if (dataContainer != null)
					NoOfRowsWithLabel = 5;

				Table table = new Table();
				for(int index = 0; index < NoOfRowsWithLabel; index++)
					AddNewRowWithLabel(table);
				
				if (dataContainer == null)
				{
					AddNewRowWithLinkButton(table, ExpenseConstants.RevenueLink);
					AddNewRowWithLinkButton(table, ExpenseConstants.CashBalanceLink);
				}

				table.DataBinding += new EventHandler(OnTableDataBinding);
				
				container.Controls.Add(table);
			}

			#endregion

			/// <summary>
			/// Handler for event when the table contained in the control binds to a datasource.
			/// Gets the dataset containing the tables for the footer template from cache using the
			/// cache policy. The method loops through all the rows in the table, retrieves the embedded
			/// control and calls a method to get the data for the control. It looks into the values for
			/// the control and formats the display of the text.
			/// </summary>
			/// <param name="sender">Control which raised the event</param>
			/// <param name="e">Argument associated with the event</param>
			private void OnTableDataBinding(object sender, EventArgs e)
			{
				Table table = (Table)sender;
				
				Hashtable h = cachePolicy.GetCachedObject(Keys.ExpenseInfoPageKey) as Hashtable;
				
				//Check if the Data for download to excel is present in cache. 
				DataSet dataContainer = (h == null) ? null : (DataSet) h[ExpenseConstants.ActiveDataForDownloadKey];
				
				if (dataContainer == null)
					dataContainer = (h == null) ? null : (DataSet) h[ExpenseConstants.ActiveDataKey];

				if(dataContainer != null)
				{
					foreach(TableRow row in table.Rows)
					{
						object control = row.Cells[FirstCellIndex].Controls[FirstControlIndex];
						if(control is Label)
						{
							Label label = (Label)control;
                            decimal amount = GetDataForControl(table.Rows.GetRowIndex(row), dataContainer);     //Decimal.Round(GetDataForControl(table.Rows.GetRowIndex(row), dataContainer), 0);
							if(amount < 0)
								label.CssClass = NegativeCurrencyStyle;
                            label.Text = PHSRAG.WebControls.Helper.ProcessDecimals(amount);     //amount.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
						}
						else if(control is LinkButton)
						{
							LinkButton linkButton = (LinkButton)control;
                            decimal amount = GetDataForControl(table.Rows.GetRowIndex(row), dataContainer);  //Decimal.Round(GetDataForControl(table.Rows.GetRowIndex(row), dataContainer), 0);
							if(amount < 0)
								linkButton.CssClass = NegativeLinkStyle;
							linkButton.Text = PHSRAG.WebControls.Helper.ProcessDecimals(amount);    //amount.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
							linkButton.CommandArgument = amount.ToString();
						}						
					}
				}
			}

			/// <summary>
			/// Retrieves and return the data from the footer tables. The method
			/// looks into the specfied row index to determine which table to get data from.
			/// It uses the cellIndex defined in this class to get the corresponding row from 
			/// the footer tables. If the column index is "0", 0th row from the direct cost and 
			/// other tables is picked to display information in the footer.
			/// </summary>
			/// <param name="rowIndex">indicates the table to fetch data from</param>
			/// <param name="dataContainer">the dataset containing the tables containing data for the 
			/// footer tables </param>
			/// <returns></returns>
			private decimal GetDataForControl(int rowIndex, DataSet dataContainer)
			{
				string valuetoAssign = DefaultAmount;
				switch((FooterCategory)rowIndex)
				{
					case FooterCategory.DirectCosts:
						valuetoAssign = dataContainer.Tables[AgreementsConstants.DirectCostsTableName].Rows
							[cellIndex][ExpenseConstants.ExpenseAmountColumnName].ToString();
						break;						
//					case FooterCategory.DirectCostBalance:
//						valuetoAssign = dataContainer.Tables[ExpenseConstants.DirectCostBalanceTableName].Rows
//							[cellIndex][ExpenseConstants.ExpenseAmountColumnName].ToString();
//						break;						
					case FooterCategory.IndirectCosts:
						valuetoAssign = dataContainer.Tables[AgreementsConstants.IndirectCostsTableName].Rows
							[cellIndex][ExpenseConstants.ExpenseAmountColumnName].ToString();
						break;						
					case FooterCategory.TotalCosts:
						valuetoAssign = dataContainer.Tables[AgreementsConstants.TotalCostsTableName].Rows
							[cellIndex][ExpenseConstants.ExpenseAmountColumnName].ToString();
						break;					
					case FooterCategory.Revenue:
						valuetoAssign = dataContainer.Tables[AgreementsConstants.RevenueTableName].Rows
							[cellIndex][ExpenseConstants.ExpenseAmountColumnName].ToString();
						break;
					case FooterCategory.CashBalance:
						valuetoAssign = dataContainer.Tables[AgreementsConstants.CashBalanceTableName].Rows
							[cellIndex][ExpenseConstants.ExpenseAmountColumnName].ToString();
						break;
					default:
						break;
				}
				return Convert.ToDecimal(valuetoAssign);
			}
			
			/// <summary>
			/// Adds a new row containing a label to the specifed table.
			/// </summary>
			/// <param name="table">table to which the row has to be added</param>
			private void AddNewRowWithLabel(Table table)
			{
				TableRow row = new TableRow();
				table.Rows.Add(row);
				TableCell cell = new TableCell();
				row.Cells.Add(cell);
				cell.Controls.Add(new Label());
			}

			/// <summary>
			/// Adds a new row containing a LinkButton to the specifed table.
			/// Sets the command name of the link button to the specifed command name
			/// and sets the style of the link button.
			/// </summary>
			/// <param name="table">table to which the row has to be added</param>
			/// <param name="commandName">command name to be specifed to the link button</param>
			private void AddNewRowWithLinkButton(Table table, string commandName)
			{
				TableRow row = new TableRow();
				table.Rows.Add(row);
				TableCell cell = new TableCell();
				row.Cells.Add(cell);
				LinkButton linkButton = new LinkButton();
				linkButton.CommandName = commandName;
				linkButton.CssClass = LinkStyle;
				cell.Controls.Add(linkButton);
			}
		}
		#endregion		
	}
}
